﻿using System;
using System.Globalization;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security;
using System.Security.Permissions;
using System.Xml;
using System.Xml.Serialization;

namespace Fly.Common
{
    /// <summary>
    /// 对象序列化类
    /// </summary>
    public class Serializer
    {
        /// <summary>
        /// 标识对象是否可以序列化
        /// </summary>
        public readonly static bool CanBinarySerialize;

        static Serializer()
        {
            SecurityPermission securityPermission = new SecurityPermission(SecurityPermissionFlag.SerializationFormatter);
            try
            {
                securityPermission.Demand();
                CanBinarySerialize = true;
            }
            catch (SecurityException)
            {
                CanBinarySerialize = false;
            }
        }
        /// <summary>
        /// 将指定路径的文件序列化成对象
        /// </summary>
        /// <param name="path"></param>
        /// <param name="objectType"></param>
        /// <returns></returns>
        public static object ConvertFileToObject(string path, Type objectType)
        {
            object obj = null;
            if (!string.IsNullOrWhiteSpace(path) && path.Length > 0)
            {
                using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                    obj = (new XmlSerializer(objectType)).Deserialize(fileStream);
                    fileStream.Close();
                }
            }
            return obj;
        }
        /// <summary>
        /// 将指定的对象序列化为 Byte 数组
        /// </summary>
        /// <param name="objectToConvert"></param>
        /// <returns></returns>
        public static byte[] ConvertToBytes(object objectToConvert)
        {
            byte[] numArray = null;
            if (CanBinarySerialize)
            {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    binaryFormatter.Serialize(memoryStream, objectToConvert);
                    memoryStream.Position = 0;
                    numArray = new byte[(int) checked((IntPtr)memoryStream.Length)];
                    memoryStream.Read(numArray, 0, numArray.Length);
                    memoryStream.Close();
                }
            }
            return numArray;
        }
        /// <summary>
        /// 将指定的 XML 片段序列化为指定的类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xml"></param>
        /// <returns></returns>
        public static T ConvertToObject<T>(string xml)where T : class
        {
            object obj = null;
            if (!string.IsNullOrEmpty(xml))
            {
                using (StringReader stringReader = new StringReader(xml))
                {
                    obj = (new XmlSerializer(typeof(T))).Deserialize(stringReader);
                    stringReader.Close();
                }
            }
            return obj as T;
        }
        /// <summary>
        /// 将指定的 XML 节点序列化为一个对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="node"></param>
        /// <returns></returns>
        public static T ConvertToObject<T>(XmlNode node)where T : class
        {
            return ConvertToObject<T>(node.OuterXml);
        }

        /// <summary>
        /// 将 Byte 数组表示的对象序列化为对象
        /// </summary>
        /// <param name="byteArray"></param>
        /// <returns></returns>
        public static object ConvertToObject(byte[] byteArray)
        {
            object obj = null;
            if (CanBinarySerialize && byteArray != null && byteArray.Length > 0)
            {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    memoryStream.Write(byteArray, 0, byteArray.Length);
                    memoryStream.Position = 0;
                    if (byteArray.Length > 4)
                    {
                        obj = binaryFormatter.Deserialize(memoryStream);
                    }
                    memoryStream.Close();
                }
            }
            return obj;
        }
        /// <summary>
        /// 将一个对象序列化为 XML 字符串
        /// </summary>
        /// <param name="objectToConvert"></param>
        /// <returns></returns>
        public static string ConvertToString(object objectToConvert)
        {
            string str = null;
            if (objectToConvert != null)
            {
                XmlSerializer xmlSerializer = new XmlSerializer(objectToConvert.GetType());
                using (StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture))
                {
                    xmlSerializer.Serialize(stringWriter, objectToConvert);
                    str = stringWriter.ToString();
                    stringWriter.Close();
                }
            }
            return str;
        }
        /// <summary>
        /// 从指定的文件路径加载文件并序列化为一个对象
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static object LoadBinaryFile(string path)
        {
            object obj;
            if (!File.Exists(path))
            {
                return null;
            }
            using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                BinaryReader binaryReader = new BinaryReader(fileStream);
                byte[] numArray = new byte[(int) checked((IntPtr)fileStream.Length)];
                binaryReader.Read(numArray, 0, (int)fileStream.Length);
                obj = ConvertToObject(numArray);
            }
            return obj;
        }
        /// <summary>
        /// 将一个对象序列化后保存到指定的路径
        /// </summary>
        /// <param name="objectToSave"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        public static bool SaveAsBinary(object objectToSave, string path)
        {
            if (objectToSave != null && CanBinarySerialize)
            {
                byte[] bytes = ConvertToBytes(objectToSave);
                if (bytes != null)
                {
                    using (FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
                    {
                        using (BinaryWriter binaryWriter = new BinaryWriter(fileStream))
                        {
                            binaryWriter.Write(bytes);
                        }
                    }
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 将指定的对象序列化为 XML 并保存到指定的路径
        /// </summary>
        /// <param name="objectToSave"></param>
        /// <param name="path"></param>
        public static void SaveAsXML(object objectToSave, string path)
        {
            if (objectToSave != null)
            {
                XmlSerializer xmlSerializer = new XmlSerializer(objectToSave.GetType());
                using (StreamWriter streamWriter = new StreamWriter(path))
                {
                    xmlSerializer.Serialize(streamWriter, objectToSave);
                    streamWriter.Close();
                }
            }
        }
    }
}
